#include "../StdInc.h"

namespace GSTrader
{
	namespace Indicator
	{
		LLVHHV::LLVHHV()
		{
			m_strIndicatorName = "LLVHHV";
			m_nLength = 0;
			m_nType = 0;
			m_nBarType = bdtClose;

			m_dMax = -DBL_MAX;
			m_dMin = DBL_MAX;
		}


		LLVHHV::~LLVHHV()
		{
		}

		CIndicator* LLVHHV::CreateInstance()
		{
			return new LLVHHV;
		}

		void LLVHHV::SetParam(int nType, int nLength, int nBarType)
		{
			m_nType = nType;
			m_nLength = nLength;
			m_nBarType = nBarType;

			RefreshData();
		}

		void LLVHHV::SetParam(double* pdParam)
		{
			if (pdParam == NULL)
				return;

			m_nType = (int)pdParam[0];
			m_nLength = (int)pdParam[1];
			m_nBarType = (int)pdParam[2];

			RefreshData();
		}

		double LLVHHV::SetMaxMinValue(int nIndex)
		{
			double dValue = m_pInput->GetValue(nIndex, m_nBarType);
			if (dValue > m_dMax)
				m_dMax = dValue;
			if (dValue < m_dMin)
				m_dMin = dValue;
	
			if (m_nType == 0) 
			{
				m_pResult->SetValue(nIndex, m_dMin);
				return m_dMin;
			}
		
			m_pResult->SetValue(nIndex, m_dMax);
			return m_dMax;
			
		}

		double LLVHHV::Calculate(int nIndex)
		{
			if (m_pInput == NULL || m_pInput->m_nStartIndex < 0 || m_nLength < 0)
				return 0;

			int nCount = m_pInput->GetCount();
			if (nIndex < m_pInput->m_nStartIndex || nIndex >= nCount)
			{
				if (nIndex >= 0 && nIndex < m_pInput->m_nStartIndex)
				{
					m_pResult->SetValue(nIndex, 0);
				}
				return 0;
			}

			double dValue = 0;
			if (m_nLength == 0)
			{
				dValue = SetMaxMinValue(nIndex);
			}
			else if (m_nLength == 1) 
			{
				dValue = m_pInput->GetValue(nIndex, m_nBarType);
				m_pResult->SetValue(nIndex, dValue);
			}
			else
			{
				int nPreData = min(m_pInput->m_nStartIndex + m_nLength, nCount);
				dValue = m_pInput->GetValue(nIndex, m_nBarType);
				if (nIndex < nPreData)
				{
					dValue = SetMaxMinValue(nIndex);
				}
				else
				{
					if (m_nType == 0)
					{
						if (m_dMin >= dValue)
						{
							m_dMin = dValue;
						}
						else
						{
							m_dMin = dValue;
							for (int j = m_nLength - 1; j >= 0; j--)
							{
								double dPre = m_pInput->GetValue(nIndex - j, m_nBarType);
								if (dPre < m_dMin)
								{
									m_dMin = dPre;
								}
							}
						}

						m_pResult->SetValue(nIndex, m_dMin);
						dValue = m_dMin;
					}
					else
					{
						if (m_dMax <= dValue)
						{
							m_dMax = dValue;
						}
						else
						{
							m_dMax = dValue;
							for (int j = m_nLength - 1; j >= 0; j--)
							{
								double dPre = m_pInput->GetValue(nIndex - j, m_nBarType);
								if (dPre > m_dMax)
								{
									m_dMax = dPre;
								}
							}
						}

						m_pResult->SetValue(nIndex, m_dMax);
						dValue = m_dMax;
					}
				}
			}

			return dValue;
		}

		void LLVHHV::RefreshData()
		{
			if (m_pInput == NULL || m_nLength < 0 || m_pInput->m_nStartIndex < 0)
			{
				m_pResult->m_pDataSeries->m_nStartIndex = -1;
				return;
			}

			int nCount = m_pInput->GetCount();

			int nStartIndex = m_pInput->m_nStartIndex;
			m_pResult->m_pDataSeries->SetSize(nCount, nStartIndex);

			m_dMax = -DBL_MAX;
			m_dMin = DBL_MAX;

			m_bCalc = true;
		}
	}
}
